package com.synnex.mobile.servier.web.common.controller;

import com.synnex.mobile.generic.core.config.service.ConfigurationService;
import com.synnex.mobile.generic.core.exception.SystemException;
import com.synnex.mobile.generic.core.pager.DataResults;
import com.synnex.mobile.generic.core.pager.Pagination;
import com.synnex.mobile.generic.core.pager.PaginationInfo;
import com.synnex.mobile.generic.core.util.*;
import com.synnex.mobile.generic.web.controller.BaseController;
import com.synnex.mobile.generic.web.multipart.MultipartFile;
import com.synnex.mobile.generic.web.multipart.MultipartRequest;
import com.synnex.mobile.generic.web.session.WebSession;
import com.synnex.mobile.generic.web.util.WebUtils;
import com.synnex.mobile.servier.core.config.ServierConfigHelper;
import com.synnex.mobile.servier.core.config.SystemKeys;
import com.synnex.mobile.servier.core.updateTime.service.UpdateTimeService;
import com.synnex.mobile.servier.web.common.session.admin.AdminSession;
import com.synnex.mobile.servier.web.common.session.mobile.MobileWebSession;
//import com.synnex.mobile.scm.core.account.bo.ProductManager;
//import com.synnex.mobile.scm.core.account.bo.User;
//import com.synnex.mobile.scm.core.account.bo.VendorUser;
//import com.synnex.mobile.scm.core.config.SCMConfigHelper;
//import com.synnex.mobile.scm.core.config.SystemKeys;
//import com.synnex.mobile.scm.web.common.session.admin.AdminWebSession;
//import com.synnex.mobile.scm.web.common.session.mobile.MobileWebSession;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.*;

/**
 * The base acer controller
 *
 * @author Lance Chen
 */
public abstract class AbstractController extends BaseController {

    protected ConfigurationService configService;

    protected UpdateTimeService updateTimeService;

    public void setConfigService(ConfigurationService configService) {
        this.configService = configService;
    }

    public void setUpdateTimeService(UpdateTimeService updateTimeService) {
        this.updateTimeService = updateTimeService;
    }

    protected MobileWebSession getMobileSession(HttpServletRequest request) {
        MobileWebSession webSession = WebSession.getCurrentSession(MobileWebSession.class, request);
        return webSession;
    }
    protected AdminSession getAdminSession(HttpServletRequest request) {
        AdminSession adminSession = WebSession.getCurrentSession(AdminSession.class, request);
        return adminSession;
    }

    protected Locale getLocale(HttpServletRequest request) {
        return WebUtils.getLocale(request);
    }

    protected String getMessage(HttpServletRequest request, String key, Object... parameters) {
        return getMessage(key, getLocale(request), parameters);
    }

    @Override
    protected Pagination createPagination(HttpServletRequest request) {
        Pagination pagination = super.createPagination(request);
        PaginationInfo paginationInfo = pagination.getPaginationInfo();
        paginationInfo.setShowTotalCount(true);
//        paginationInfo.setTotalCountTips(getMessage(request, "pagination.tips.total"));
//        paginationInfo.setPreButtonTips(getMessage(request, "pagination.tips.pre"));
//        paginationInfo.setNextButtonTips(getMessage(request, "pagination.tips.next"));
//        paginationInfo.setPreButtonDisabledTips("<span class=\"current prev\">" + paginationInfo.getPreButtonTips() + "</span>");
//        paginationInfo.setNextButtonDisabledTips("<span class=\"current next\">" + paginationInfo.getNextButtonTips() + "</span>");
        return pagination;
    }

    protected ServierConfigHelper getConfig() {
        ServierConfigHelper helper = this.configService.getHelper(SystemKeys.APP_NAME, ServierConfigHelper.class);
        return helper;
    }

    /*
     * Below are for the test data methods.
     */
    protected <T> T createUniqueTestData(Class<T> clazz, String[] ignoreProperties) {
        return createUniqueTestData(clazz, ignoreProperties, 0);
    }

    protected <T> List<T> createListTestData(Class<T> clazz, String[] ignoreProperties) {
        return createListTestData(clazz, ignoreProperties, 10);
    }

    protected <T> List<T> createListTestData(Class<T> clazz, String[] ignoreProperties, int size) {
        List<T> list = new ArrayList<T>();
        for (int index = 0; index < size; index++) {
            list.add(createUniqueTestData(clazz, ignoreProperties, index));
        }
        return list;
    }

    @SuppressWarnings("unchecked")
    protected <T> Map<String, Object> createPaginationTestData(Class<T> clazz, String[] ignoreProperties, HttpServletRequest request) {
        int totalCount = 100;
        Pagination pagination = createPagination(request);
        pagination.setTotalCount(totalCount);
        List<T> list = new ArrayList<T>();
        for (int index = pagination.getBegin(); index < (pagination.getBegin() + pagination.getOffset()); index++) {
            list.add(createUniqueTestData(clazz, ignoreProperties, index));
        }
        DataResults<T> results = DataResults.create(totalCount, list, pagination);
        Map<String, Object> model = new HashMap<String, Object>();
        model.put("totalCount", results.getTotalCount());
        model.put("pageNo", pagination.getPageNo());
        model.put("pageSize", pagination.getPageSize());
        model.put("results", results.getResults());
        model.put("dataWrap", results);
        return model;
    }

    private <T> T createUniqueTestData(Class<T> clazz, String[] ignoreProperties, int index) {
        T instance = ReflectionUtil.newInstance(clazz);
        if (isJavaClass(clazz)) {
            return instance;
        }
        if (clazz == String.class) {
            instance = (T) ("Test" + (index > 0 ? String.valueOf(index) : ""));
            return instance;
        }
        Field[] fields = ReflectionUtil.getNonStaticFields(clazz);
        for (Field field : fields) {
            try {
                if (ignoreProperties != null) {
                    for (String ignoreSource : ignoreProperties) {
                        if (field.getName().equals(ignoreSource)) {
                            continue;
                        }

                    }
                }
                setFieldTestData(instance, field, ignoreProperties, index);
            } catch (Exception ex) {
                ex.printStackTrace();
                continue;
            }
        }
        return instance;
    }

    private <T> boolean isJavaClass(Class<T> clazz) {
        return clazz == Date.class;
    }

    private void setFieldTestData(Object instance, Field field, String[] ignoreProperties, int index) {
        Class<?> fieldType = field.getType();
        Object value = null;
        if (fieldType == boolean.class || fieldType == Boolean.class) {
            value = Boolean.TRUE;
        } else if (fieldType == int.class || fieldType == Integer.class) {
            value = index + 1;
        } else if (fieldType == float.class || fieldType == Float.class) {
            value = 1.00;
        } else if (fieldType == double.class || fieldType == Double.class) {
            value = 10.00;
        } else if (fieldType == long.class || fieldType == Long.class) {
            value = 64;
        } else if (fieldType == byte.class || fieldType == Byte.class) {
            value = 8;
        } else if (fieldType == short.class || fieldType == Short.class) {
            value = 16;
        } else if (fieldType == String.class) {
            value = "Test" + (index > 0 ? String.valueOf(index) : "") + " " + field.getName();
        } else if (fieldType == Date.class) {
            value = new Date();
        } else if (fieldType == BigDecimal.class) {
            value = new BigDecimal(12.00);
        } else if (fieldType.isAssignableFrom(List.class)) {
            value = new ArrayList<Object>();
        } else if (fieldType.isAssignableFrom(Map.class)) {
            value = new HashMap<String, Object>();
        } else {
            value = createUniqueTestData(fieldType, ignoreProperties);
        }
        ReflectionUtil.invokeSetter(instance, field.getName(), value);
    }

    protected MultiValueMap<String, String> uploadFilesToFtp(HttpServletRequest request, String name,String fileName) {
        MultiValueMap<String, String> results = new LinkedMultiValueMap<String, String>(1);
        MultipartRequest multipartRequest = (MultipartRequest) request;
        List<MultipartFile> files = multipartRequest.getFiles(name);
        for (MultipartFile multipartFile : files) {
            try {
                if (multipartFile.isEmpty()) {
                    continue;
                }
                String fileSufix = FileUtil.getFileSuffix(multipartFile.getOriginalFilename());
                String data = "";
                if(null == fileName){
//                    data = FormatUtil.formatDate("yyyyMMddhhmmssSS", new Date());
                    data = UUID.randomUUID().toString().replaceAll("-","");
                }else{
                    data = fileName;
                }

                FileUtil.ftpUpload(getConfig().getFtpHost(), getConfig().getFtpPort(),
                        getConfig().getFtpUserName(), getConfig().getFtpPwd(),
                        getConfig().getFtpUploadPath(), data+"."+fileSufix, multipartFile.getInputStream());

                results.add(name, data+"."+fileSufix);
            } catch (Exception ex) {
                throw new SystemException("File [" + multipartFile.getOriginalFilename() + "] can't be upload.");
            }
        }
        return results;
    }



}
